import Router from 'koa-router';
import { PassThrough, Transform } from 'stream';
import { IBatchSend } from '../types/base';
import WSS from '../wss';

let count = 0;

const connectionMap: Record<string, any> = {};
const ids = [];

const writeToStream = (stream: Transform, type: string, data: any) => {
  const payload = { type, data };
  stream.write(`data: ${JSON.stringify(payload)}\n\n`);
};

const closeStream = (stream: Transform) => {
  writeToStream(stream, 'close', '');
  stream.destroy();
};

// Base //localhost:8899/plugin.bridge/
// For help see https://github.com/ZijianHe/koa-router#api-reference
export default (router: Router, wss: WSS) => {
  // 【dev】调试web页面
  router.get('/a', ctx => {
    // 实现请求重定向 http://127.0.0.1:5173/
    ctx.redirect('http://127.0.0.1:5173/');
  });

  router.get('/sse', ctx => {
    ctx.req.socket.setTimeout(0);
    ctx.req.socket.setNoDelay(true);
    ctx.req.socket.setKeepAlive(true);
    ctx.set({
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    });

    const stream = new PassThrough();
    const name = ctx.request.query['name'] as string;

    try {
      Object.defineProperty(connectionMap[name], 'stream', {
        value: stream,
        enumerable: false,
      });
    } catch (error) {
      console.error(connectionMap, name);
    }

    wss.addReceivedHandle(data => {
      const parsedData = JSON.parse(data);
      if (parsedData.name && parsedData.name !== name) {
        return;
      }
      writeToStream(stream, parsedData.type, parsedData.data);
    });

    ctx.status = 200;
    ctx.body = stream;
    writeToStream(stream, 'establish', new Date().toLocaleString());
  });

  router.post('/info', ctx => {
    const data = ctx.request.body as any;
    if (connectionMap[data.name]) {
      closeStream(connectionMap[data.name].stream);
    }

    connectionMap[data.name] = {
      name: data.name,
      ip: ctx.request.ip,
      data: data.data,
      originBridgeKey: data.originBridgeKey,
      receiveName: data.receiveName,
      status: 'online',
    };

    Object.defineProperty(connectionMap[data.name], 'callHistory', {
      value: [],
      enumerable: false,
    });

    ctx.body = { t: Date.now(), data };
  });

  router.post('/batchSend', ctx => {
    const name = ctx.request.query['name'] as string;
    const datas = ctx.request.body as unknown as IBatchSend[];

    datas.forEach(data => {
      switch (data.type) {
        case 'CALL':
          data.id = data.time + '-' + count++;
          ids.push(data.id);
          connectionMap[name].callHistory.push(data);
          break;
        default:
          console.log('unknow type', data);
          break;
      }
    });

    wss.sendData(connectionMap);
    ctx.body = { t: Date.now() };
  });

  // --------------------------------

  router.get('/cgi-bin/infos', ctx => {
    ctx.body = {
      data: connectionMap,
      status_code: 0,
      status_msg: 'ok',
    };
  });

  router.get('/cgi-bin/history/:name', ctx => {
    const { name } = ctx.params;
    if (!connectionMap[name]) {
      ctx.body = {
        status_code: -1,
        status_msg: 'name not found',
      };
      return;
    }

    ctx.body = {
      status_code: 0,
      data: connectionMap[name].callHistory,
    };
  });

  router.get('/cgi-bin/remove/:name', ctx => {
    const { name } = ctx.params;
    if (name) {
      const info = connectionMap[name];
      if (info) {
        closeStream(info.stream);
        delete connectionMap[name];
      }
    } else {
      Object.keys(connectionMap).forEach(key => {
        const info = connectionMap[key];
        if (info) {
          closeStream(info.stream);
          delete connectionMap[key];
        }
      });
    }

    ctx.body = {
      data: connectionMap,
      status_code: 0,
      status_msg: 'ok',
    };
  });

  // --------------------------------

  router.get('/cgi-bin/wspage', ctx => {
    ctx.type = 'text/html';
    ctx.body = `<!DOCTYPE html>
    <html>
      <body><script>
          var ws = new WebSocket('ws://127.0.0.1:8899/plugin.bridge/ws');
          ws.onopen = function () {
            alert('Connected to the WebSocket server');
            ws.send('Hello from the client!');
            setTimeout(() => ws.close(),1000)
          };
          ws.onclose = function () { console.log('ws close')  }
      </script>ws status test</body>
    </html>    
    `;
  });
};
